const { toString } = Object.prototype;

/**
 * 是否为方法
 *
 * @export
 * @param {*} fn 需要判断的方法
 * @return {*}  {boolean}
 */
export function isFunc(fn: any): boolean {
  return typeOf(fn) === 'function';
}

/**
 * 是否为异步方法
 *
 * @export
 * @param {*} fn 需要判断的方法
 * @return {*}  {boolean}
 */
export function isAsync(fn: unknown): boolean {
  return toString.call(fn) === '[object AsyncFunction]';
}

/**
 * 是否为Promise对象
 *
 * @export
 * @param {*} obj
 * @return {*}  {boolean}
 */
export function isPromise(obj: unknown): boolean {
  return toString.call(obj) === '[object Promise]';
}

/**
 * 是否为对象类型
 *
 * @export
 * @param {*} obj
 * @return {*}  {boolean}
 */
export function isObject(obj: unknown): boolean {
  return typeOf(obj) === 'object';
}

/**
 * 是否为数组类型
 *
 * @export
 * @param {*} obj
 * @return {*}  {boolean}
 */
export function isArray(obj: unknown): boolean {
  return typeOf(obj) === 'array';
}

/**
 * 是否为 Map 类型
 *
 * @author chitanda
 * @date 2022-09-07 23:09:05
 * @export
 * @param {unknown} obj
 * @return {*}  {boolean}
 */
export function isMap(obj: unknown): boolean {
  return typeOf(obj) === 'map';
}

/**
 * 是否为 WeakMap 类型
 *
 * @author chitanda
 * @date 2022-09-07 23:09:25
 * @export
 * @param {unknown} obj
 * @return {*}  {boolean}
 */
export function isWeakMap(obj: unknown): boolean {
  return typeOf(obj) === 'weakmap';
}

/**
 * 是否为 Set 类型
 *
 * @author chitanda
 * @date 2022-09-07 23:09:54
 * @export
 * @param {unknown} obj
 * @return {*}  {boolean}
 */
export function isSet(obj: unknown): boolean {
  return typeOf(obj) === 'set';
}

/**
 * 是否为字符串类型
 *
 * @export
 * @param {*} obj
 * @return {*}  {boolean}
 */
export function isString(obj: any): boolean {
  return typeOf(obj) === 'string';
}

/**
 * 是否为数值类型
 *
 * @export
 * @param {*} obj
 * @return {*}  {boolean}
 */
export function isNumber(obj: unknown): boolean {
  return typeOf(obj) === 'number';
}

/**
 * 是否为布尔类型
 *
 * @export
 * @param {*} obj
 * @return {*}  {boolean}
 */
export function isBoolean(obj: unknown): boolean {
  return typeOf(obj) === 'boolean';
}

/**
 * 支持判断的数据类型
 */
const typeMap: Record<string, string> = {
  '[object Boolean]': 'boolean',
  '[object Number]': 'number',
  '[object String]': 'string',
  '[object Function]': 'function',
  '[object Array]': 'array',
  '[object Date]': 'date',
  '[object RegExp]': 'regExp',
  '[object Undefined]': 'undefined',
  '[object Null]': 'null',
  '[object Object]': 'object',
  '[object Set]': 'set',
  '[object Map]': 'map',
  '[object WeakMap]': 'weakmap',
};

/**
 * 判断数据类型
 *
 * @author chitanda
 * @date 2021-05-18 11:05:23
 * @export
 * @param {*} obj 需要判断的数据
 * @return {*}  {('boolean' | 'number' | 'string' | 'function' | 'array' | 'date' | 'regExp' | 'undefined' | 'null' | 'object')}
 */
export function typeOf(
  obj: unknown,
):
  | 'boolean'
  | 'number'
  | 'string'
  | 'function'
  | 'array'
  | 'date'
  | 'regExp'
  | 'undefined'
  | 'null'
  | 'object'
  | 'set'
  | 'map'
  | 'weakmap' {
  return typeMap[toString.call(obj)] as any;
}
